package demo.c1;

import org.junit.Test;

import java.util.stream.IntStream;

/**
 * ThreadContructorDemo
 *
 * @author chisheng
 */
public class ThreadContructorDemo {

    /* Thread()
     * Thread (Runnable target)
     * Thread (Runnable target, String name)
     * Thread (String name)
     * Thread (ThreadkjGroup group, Runnable target)
     * Thread (ThreadGroup group, Runnable target, String name)
     * Thread (ThreadGroup group, Runnable target, String name, long stackSize)
     * Thread (ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals)
     * Thread (ThreadGroup group, String name) */

    @Test
    public void test01() {

        /* Thread()
         * Thread (Runnable target)
         * Thread (ThreadGroup group, Runnable target)
         *  Automatically generated names are of the form "Thread-"+n, where n is an integer. */

        IntStream.range(0, 5).boxed().map(i -> new Thread() {
            @Override
            public void run() {
                System.out.println(this.getName());
            }
        }).forEach(Thread::start);
    }

    @Test
    public void test02() {

        /* Thread (String name)
         * Thread (Runnable target, String name)
         * Thread (ThreadGroup group, Runnable target, String name)
         * Thread (ThreadGroup group, Runnable target, String name, long stackSize)
         * Thread (ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals) */

        String prefix = "chisheng-";
        IntStream.range(0, 5).mapToObj(i -> new Thread(() ->
                System.out.println(Thread.currentThread().getName()), prefix + i)
        ).forEach(Thread::start);

        /* public final synchronized void setName(String name) {
         *     checkAccess();
         *     if (name == null) {
         *         throw new NullPointerException("name cannot be null");
         *     }
         *
         *     // 实例存在即可修改线程名称，且该名称不同线程可重复
         *     this.name = name;
         *     if (threadStatus != 0) {
         *         setNativeName(name);
         *      }
         * } */
        final Thread thread = new Thread(() -> System.out.println(Thread.currentThread().getName()));
        thread.setName("New Name");
        thread.start();
    }

    @Test
    public void test03() {

        /* private Thread(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
         *     ...
         *     SecurityManager security = System.getSecurityManager();
         *     if (g == null) {
         *         // Determine if it's an applet or not
         *         // If there is a security manager, ask the security manager what to do.
         *         if (security != null) {
         *             g = security.getThreadGroup();
         *         }
         *
         *         // If the security manager doesn't have a strong opinion on the matter, use the parent thread group.
         *         if (g == null) {
         *             g = parent.getThreadGroup();
         *         }
         *     }
         *     ...
         * } */

        // Print the main thread's ThreadGroup
        System.out.println("main thread: " + Thread.currentThread().getThreadGroup());

        // Not given ThreadGroup parameter
        final Thread thread0 = new Thread(() -> { });
        System.out.println("thread0: " + thread0.getThreadGroup());

        // Specific ThreadGroup paramater
        final ThreadGroup threadGroup = new ThreadGroup("MyThreadGroup");
        final Thread thread1 = new Thread(threadGroup, () -> { });
        System.out.println("thread1: " + thread1.getThreadGroup());
    }

    @Test
    public void test04() {

        /* Thread (ThreadGroup group, Runnable target, String name, long stackSize)
         * Thread (ThreadGroup group, Runnable target, String name, long stackSize, boolean inheritThreadLocals)
         *
         * The stack size is the approximate number of bytes of address space that the
         * virtual machine is to allocate for this thread's stack.
         * The effect of the stackSize parameter, if any, is highly platform dependent.
         * On some platforms, specifying a higher value for the stackSize parameter may
         * allow a thread to achieve greater recursion depth before throwing a StackOverflowError.
         * Similarly, specifying a lower value may allow a greater number of threads to exist concurrently
         * without throwing an OutOfMemoryError (or other internal error).
         * The details of the relationship between the value of the stackSize parameter
         * and the maximum recursion depth and concurrency level are platform-dependent.
         * On some platforms, the value of the stackSize parameter may have no effect whatsoever. */

        final Thread thread = new Thread(Thread.currentThread().getThreadGroup(), () -> { }, "Thread", 10);
        thread.start();
    }

}
